package cn.schoolwow.quickdao.module.database.parent.flow.executor.common;

import cn.schoolwow.quickflow.domain.FlowContext;
import cn.schoolwow.quickflow.flow.BusinessFlow;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.sql.Date;
import java.sql.Time;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Collection;

public class SetFormatStatementFlow implements BusinessFlow {
    private Logger logger = LoggerFactory.getLogger(SetFormatStatementFlow.class);

    /**
     * SQL参数占位符
     */
    private static final String PLACEHOLDER = "** NOT SPECIFIED **";

    /**
     * 格式化旧版本的java.sql.Date类型
     */
    private final static SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");

    /**
     * 格式化旧版本的java.sql.Time类型
     */
    private final static SimpleDateFormat simpleTimeFormat = new SimpleDateFormat("HH:mm:ss");
    /**
     * 格式化旧版本的Timestampt类型
     */
    private final static SimpleDateFormat simpleDateTimeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");
    /**
     * 格式化日期参数
     */
    private final static DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
    /**
     * 格式化日期参数
     */
    private final static DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    @Override
    public void executeBusinessFlow(FlowContext flowContext) throws Exception {
        String sql = (String) flowContext.checkData("sql");
        Collection parameters = (Collection) flowContext.getData("parameters");

        if(null==parameters||parameters.isEmpty()){
            flowContext.putTemporaryData("formatSQL", sql);
            flowContext.brokenCurrentFlow("");
        }
        //判断参数个数是否匹配
        int parameterCount = 0;
        for(int i=0;i<sql.length();i++){
            if(sql.charAt(i)=='?'){
                parameterCount++;
            }
        }
        if(parameterCount!=parameters.size()){
            logger.warn("参数个数不匹配!预期参数个数:{},实际参数个数:{},\r\n语句:{}\r\n参数列表:{}", parameterCount, parameters.size(), sql, parameters);
            throw new IllegalArgumentException("参数个数不匹配!预期个数:"+parameterCount+",实际个数:"+parameters.size());
        }
        StringBuilder sqlBuilder = new StringBuilder(sql.replace("?", PLACEHOLDER));
        for (Object parameter : parameters) {
            String parameterPlaceHolder = getParameterPlaceHolder(parameter);
            int indexOf = sqlBuilder.indexOf(PLACEHOLDER);
            sqlBuilder.replace(indexOf, indexOf + PLACEHOLDER.length(), parameterPlaceHolder);
        }
        String formatSQL = sqlBuilder.toString();
        flowContext.putTemporaryData("formatSQL", formatSQL);
    }

    @Override
    public String name() {
        return "设置格式化SQL语句";
    }

    /**
     * 获取参数占位符
     *
     * @param parameter 参数值
     */
    private String getParameterPlaceHolder(Object parameter) {
        if (null == parameter) {
            return "null";
        }
        String parameterSQL = parameter.toString();
        switch (parameter.getClass().getName()) {
            case "boolean": {
                boolean value = (boolean) parameter;
                parameterSQL = value ? "1" : "0";
            }
            break;
            case "java.lang.String":
            case "com.alibaba.fastjson.JSONObject":
            case "com.alibaba.fastjson.JSONArray": {
                parameterSQL = "'" + parameter.toString() + "'";
            }
            break;
            case "java.util.Date": {
                java.util.Date date = (java.util.Date) parameter;
                parameterSQL = "'" + simpleDateFormat.format(date) + "'";
            }
            break;
            case "java.sql.Date": {
                Date date = (Date) parameter;
                parameterSQL = "'" + simpleDateFormat.format(date) + "'";
            }
            break;
            case "java.sql.Time": {
                Time time = (Time) parameter;
                parameterSQL = "'" + simpleTimeFormat.format(time) + "'";
            }
            break;
            case "java.sql.Timestamp": {
                Timestamp timestamp = (Timestamp) parameter;
                parameterSQL = "'" + simpleDateTimeFormat.format(timestamp) + "'";
            }
            break;
            case "java.time.LocalDate": {
                LocalDate localDate = (LocalDate) parameter;
                parameterSQL = "'" + localDate.format(dateFormatter) + "'";
            }
            break;
            case "java.time.LocalDateTime": {
                LocalDateTime localDateTime = (LocalDateTime) parameter;
                parameterSQL = "'" + localDateTime.format(dateTimeFormatter) + "'";
            }
            break;
        }
        return parameterSQL;
    }
}
